﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;

namespace Common
{
    /// <summary>
    /// 
    /// </summary>
    public class DataTableUtil
    {
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dtObj"></param>
        /// <returns></returns>
        public static List<T> ToList<T>(DataTable dtObj)
        {
            List<T> objList=new List<T>();
            Dictionary<string,PropertyInfo> propDict=new Dictionary<string, PropertyInfo>();
            PropertyInfo[] props = typeof (T).GetProperties();
            foreach(PropertyInfo prop in props)
                propDict.Add(prop.Name, prop);
            if(dtObj !=null && dtObj.Rows.Count>0)
            {
                foreach(DataRow dr in dtObj.Rows)
                {
                    T t = (T) Activator.CreateInstance(typeof (T));
                    foreach(string propName in propDict.Keys)
                    {
                        if(dtObj.Columns.Contains(propName) && dr[propName]!=DBNull.Value)
                        {
                            object fieldValue = dr[propName];
                            propDict[propName].SetValue(t, fieldValue, null);
                        }
                    }
                    objList.Add(t);
                }
            }
            return objList;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dtObj"></param>
        /// <param name="propColNameMappings"></param>
        /// <returns></returns>
        public static List<T> ToList<T>(DataTable dtObj, Dictionary<string,string> propColNameMappings)
        {
            List<T> objList = new List<T>();
            Dictionary<string, PropertyInfo> propDict = new Dictionary<string, PropertyInfo>();
            PropertyInfo[] props = typeof(T).GetProperties();
            foreach (PropertyInfo prop in props)
                propDict.Add(prop.Name, prop);
            if (dtObj != null && dtObj.Rows.Count > 0)
            {
                foreach (DataRow dr in dtObj.Rows)
                {
                    T t = (T)Activator.CreateInstance(typeof(T));
                    foreach (string propName in propDict.Keys)
                    {
                        string fieldName = propName;
                        if (propColNameMappings != null && propColNameMappings.ContainsKey(propName))
                            fieldName = propColNameMappings[propName];
                        if (dtObj.Columns.Contains(fieldName) && dr[fieldName] != DBNull.Value)
                        {
                            object fieldValue = dr[fieldName];
                            propDict[propName].SetValue(t, fieldValue, null);
                        }
                    }
                    objList.Add(t);
                }
            }
            return objList;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="objList"></param>
        /// <param name="tblName"></param>
        /// <returns></returns>
        public static DataTable ToTable<T>(List<T> objList, string tblName)
        {
            DataTable dtObj=new DataTable(tblName);
            PropertyInfo[] props = typeof (T).GetProperties();
            foreach(PropertyInfo prop in props)
            {
                dtObj.Columns.Add(prop.Name, prop.PropertyType);
            }
            if (objList != null && objList.Count > 0)
            {
                foreach (T obj in objList)
                {
                    DataRow dr = dtObj.NewRow();
                    foreach (PropertyInfo prop in props)
                    {
                        object propValue = prop.GetValue(obj, null);
                        if (propValue != null)
                            dr[prop.Name] = propValue;
                    }
                    dtObj.Rows.Add(dr);
                }
            }
            return dtObj;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="objList"></param>
        /// <param name="tblName"></param>
        /// <param name="propColNameMappings"></param>
        /// <returns></returns>
        public static DataTable ToTable<T>(List<T> objList, string tblName, Dictionary<string, string> propColNameMappings)
        {
            DataTable dtObj = new DataTable(tblName);
            PropertyInfo[] props = typeof(T).GetProperties();
            foreach (PropertyInfo prop in props)
            {
                string fieldName = prop.Name;
                if (propColNameMappings != null && propColNameMappings.ContainsKey(prop.Name))
                    fieldName = propColNameMappings[prop.Name];
                dtObj.Columns.Add(fieldName, prop.PropertyType);
            }
            if (objList != null && objList.Count > 0)
            {
                foreach (T obj in objList)
                {
                    DataRow dr = dtObj.NewRow();
                    foreach (PropertyInfo prop in props)
                    {
                        object propValue = prop.GetValue(obj, null);
                        if (propValue != null)
                        {
                            string fieldName = prop.Name;
                            if (propColNameMappings != null && propColNameMappings.ContainsKey(prop.Name))
                                fieldName = propColNameMappings[prop.Name];
                            dr[fieldName] = propValue;
                        }
                    }
                    dtObj.Rows.Add(dr);
                }
            }
            return dtObj;
        }
    }
}
